package com.region.plugin.proxy.javassist;

import com.region.plugin.Interceptor;
import com.region.plugin.proxy.ProxyHandler;
import javassist.util.proxy.ProxyFactory;

import java.lang.reflect.InvocationTargetException;
import java.util.List;

/**
 * @author liujieyu
 * @date 2024/11/6 11:00
 * @desciption
 */
public class JavassistProxyHandler implements ProxyHandler {

    // save the class of target object
    private ThreadLocal<Class<?>> superClassLocal = new ThreadLocal<Class<?>>() {
        @Override
        protected Class<?> initialValue() {
            return null;
        }
    };

    @Override
    public Object createProxyInstance(Object target, Class<?>[] classes, Interceptor interceptor, Object[] args) {
        ProxyFactory proxyFactory = new ProxyFactory();
        if (classes == null || classes.length == 0) {
            // no interface class
            proxyFactory.setInterfaces(classes);
        } else {
            if (superClassLocal.get() == null) {
                superClassLocal.set(target.getClass());
            }
            proxyFactory.setSuperclass(superClassLocal.get());
        }
        try {
            return proxyFactory.create(getArgsClasses(args), args, new JavassistRealProxy(target, interceptor));
        } catch (InstantiationException|InvocationTargetException|NoSuchMethodException|IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void completeProxy(Object target, List<Interceptor> interceptors, Object[] args) {
        superClassLocal.remove();
    }

    private Class<?>[] getArgsClasses(Object[] args) {
        if (args == null) {
            return null;
        }
        if (args.length == 0) {
            return new Class<?>[0];
        }
        Class<?>[] argsClass = new Class<?>[args.length];
        for (int i = 0; i < args.length; i++) {
            argsClass[i] = args[i].getClass();
        }
        return argsClass;
    }
}
